#include "Room.hh"
#include <iostream>
#include <sstream>
using namespace std;

// Room base class constructor
Room::Room(const string& name, const string& description)
    : name(name), description(description) {}

// Destructor, releases all items and enemies in the room
// Note: Ensure that enemies that have been deleted in the game are not deleted again
Room::~Room() 
{
    for (auto item : items) {
        delete item;
    }
    for (auto enemy : enemies) {
        delete enemy;
    }
}


// Set room exit
void Room::setExit(const string& direction, Room* neighbor) 
{
    exits[direction] = neighbor;
}

// Get adjacent room based on direction
Room* Room::getExit(const string& direction) const 
{
    auto it = exits.find(direction);
    if (it != exits.end()) {
        return it->second;
    }
    return nullptr;
}

// Return direction of the room
string Room::getExitsString() const 
{
    stringstream ss;
    for (auto& exit : exits) //reference
    {
        ss << exit.first << " ";
    }
    return ss.str(); //stringstream to string
}

// Add item to the room
void Room::addItem(Item* item) 
{
    items.push_back(item);
}

// Take a specified item from the room
Item* Room::takeItem(const string& itemName) 
{
    for (size_t i = 0; i < items.size(); i++) {
        if (items[i]->name == itemName) 
        {
            Item* item = items[i];
            items.erase(items.begin() + i);
            return item;
        }
    }
    return nullptr;
}

// Get string list of items in the room
string Room::getItemsString() const 
{
    stringstream ss;
    if (items.empty()) 
    {
        ss << "None";
    }
    else 
    {
        for (auto item : items) 
        {
            ss << item->name << " ";
        }
    }
    return ss.str();
}

// Add enemy to the room
void Room::addEnemy(ICharacter* enemy) 
{
    enemies.push_back(enemy);
}

// Get enemy pointer by enemy name
ICharacter* Room::getEnemy(const string& enemyName) 
{
    for (auto enemy : enemies) 
    {
        if (enemy->getName() == enemyName) 
        {
            return enemy;
        }
    }
    return nullptr;
}

// Get string description of all enemies in the room
string Room::getEnemiesString() const 
{
    stringstream ss;
    if (enemies.empty()) 
    {
        ss << "None";
    }
    else 
    {
        for (auto enemy : enemies) 
        {
            ss << enemy->getName() << "(HP:" << enemy->getHealth() << ") ";
        }
    }
    return ss.str();
}

// Remove a specified enemy from the room
void Room::removeEnemy(ICharacter* enemy) 
{
    for (auto it = enemies.begin(); it != enemies.end(); it++)
    {
        if (*it == enemy) 
        {
            enemies.erase(it);
            break;
        }
    }
}

// Display room information
void Room::display() const 
{
    cout << "=== " << name << " ===\n";
    cout << description << "\n\n";
    cout << "Items in the room: " << getItemsString() << "\n";
    cout << "Enemies: " << getEnemiesString() << "\n";
    cout << "Exits: " << getExitsString() << "\n";
}

string Room::getName() const 
{
    return name;
}

// Operator overload: access adjacent room by direction using operator[]
Room* Room::operator[](const std::string& direction) 
{
    return getExit(direction);
}
